package com.yhk.usercenter.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;

import com.yhk.usercenter.common.ErrorCode;
import com.yhk.usercenter.exception.BusinessException;
import com.yhk.usercenter.mapper.UserMapper;
import com.yhk.usercenter.model.domain.User;
import com.yhk.usercenter.service.UserService;


import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.util.DigestUtils;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

import static com.yhk.usercenter.constant.UserConstant.USER_LOGIN_STATUS;

/**
* @author moresuo
* @description 针对表【user(用户表)】的数据库操作Service实现
* @createDate 2023-12-02 16:34:23
*/
@Service
@Slf4j
public class UserServiceImpl extends ServiceImpl<UserMapper,User>
    implements UserService {
    @Resource
    private UserMapper userMapper;
    private static final String SALT="yhk";//加盐,混淆密码

    @Override
    public long userRegister(String userAccount, String userPassword, String checkPassword,String planetCode) {
        //1. 校验
        if(StringUtils.isAnyBlank(userAccount,userPassword,checkPassword,planetCode)){//校验所含字符串是否为空，或者长度为0
            throw new BusinessException(ErrorCode.PARAMS_ERROE,"参数为空");
        }
        if(userAccount.length()<4){
            throw new BusinessException(ErrorCode.PARAMS_ERROE,"账号过短");
        }
        if(userPassword.length()<8||checkPassword.length()<8){
            throw new BusinessException(ErrorCode.PARAMS_ERROE,"密码过短");
        }
        if(planetCode.length()>5){
            throw new BusinessException(ErrorCode.PARAMS_ERROE,"星球编号过长");
        }
        //校验账户不能包含特殊字符
        String regEx = "\\pP|\\pS|\\s+";
        Matcher matcher = Pattern.compile(regEx).matcher(userAccount);
        if(matcher.find()){//匹配到特殊字符
            throw new BusinessException(ErrorCode.PARAMS_ERROE, "不能包含特殊字符");
        }
        if(!userPassword.equals(checkPassword)){
            throw new BusinessException(ErrorCode.PARAMS_ERROE, "密码不一致");
        }
        //账户不能重复，查询数据库中有没有相同的账户,可以将查询数据库放到最后，如果前面的条件都满足的话，在进行查询数据库，因为查询数据库是最耗费时间的
        long count = userMapper.selectCount(new QueryWrapper<User>().eq("userAccount", userAccount));
        if(count>0){
            throw new BusinessException(ErrorCode.PARAMS_ERROE, "账户已存在");
        }
        //星球编号不能重复
        count = userMapper.selectCount(new QueryWrapper<User>().eq("planetCode", planetCode));
        if(count>0){
            throw new BusinessException(ErrorCode.PARAMS_ERROE, "账户已存在");
        }
        //2. 对密码进行加密
        String encryptPassword = DigestUtils.md5DigestAsHex((SALT + userPassword).getBytes());
        // 3.插入数据
        User user=new User();
        user.setUserAccount(userAccount);
        user.setPassword(encryptPassword);
        user.setPlanetCode(planetCode);
        boolean saveResult = this.save(user);
        if(!saveResult){
            throw new RuntimeException();
        }
        return user.getId();//id为Long类型，但是返回的是long类型，如果返回一个null的话将会报错
    }

    @Override
    public User userLogin(String userAccount, String userPassword, HttpServletRequest request) {
        //校验
        if(StringUtils.isAnyBlank(userAccount,userPassword)){
            throw new BusinessException(ErrorCode.PARAMS_NULL_ERROE, "参数为空");
        }
        if(userAccount.length()<4){
            throw new BusinessException(ErrorCode.PARAMS_ERROE, "账号长度过小");
        }
        if(userPassword.length()<8){
            throw new BusinessException(ErrorCode.PARAMS_ERROE, "密码长度过小");
        }
        //账户不能包含特殊字符
        String regEx = "\\pP|\\pS|\\s+";
        Matcher matcher = Pattern.compile(regEx).matcher(userAccount);
        if(matcher.find()){
            throw new BusinessException(ErrorCode.PARAMS_ERROE, "包含特殊字符");
        }
        //将登录的密码进行加密，然后与数据库中的密码进行对比
        String entryPassword=DigestUtils.md5DigestAsHex((SALT+userPassword).getBytes());
        //根据账户和密码查询用户信息
        QueryWrapper<User> queryWrapper=new QueryWrapper<>();
        queryWrapper.eq("userAccount", userAccount);
        queryWrapper.eq("password", entryPassword);
        User user = userMapper.selectOne(queryWrapper);
        //用户不存在
        if(user==null){
            log.info("user login failed,userAccount cannot match userPassword");
            throw new BusinessException(ErrorCode.PARAMS_ERROE, "用户不存在");
        }
        //用户脱敏
        User safeUser = getSafeUser(user);
        //记录用户登录态
        request.getSession().setAttribute(USER_LOGIN_STATUS, safeUser);
        return safeUser;
    }

    @Override
    public List<User> searchUsers() {
        QueryWrapper<User> queryWrapper = new QueryWrapper<>();
        List<User> userList= this.list(queryWrapper);
        return userList.stream().map(user -> getSafeUser(user)).collect(Collectors.toList());
    }

    /**
     * 将原生user对象进行脱敏
     * @param originUser 原生user
     * @return
     */
    @Override
    public User getSafeUser(User originUser) {
        if(originUser==null){
            return null;
        }
        User safeUser=new User();
        safeUser.setId(originUser.getId());
        safeUser.setUsername(originUser.getUsername());
        safeUser.setUserAccount(originUser.getUserAccount());
        safeUser.setAvatarUrl(originUser.getAvatarUrl());
        safeUser.setGender(originUser.getGender());
        safeUser.setPhone(originUser.getPhone());
        safeUser.setEmail(originUser.getEmail());
        safeUser.setPlanetCode(originUser.getPlanetCode());
        safeUser.setUserRole(originUser.getUserRole());
        safeUser.setStatus(originUser.getStatus());
        safeUser.setCreateTime(originUser.getCreateTime());
        return safeUser;
    }

    @Override
    public int userLogout(HttpServletRequest request) {
        request.getSession().removeAttribute(USER_LOGIN_STATUS);//将用户状态从session中移除
        return 1;
    }
}




